package com.cisdi.blog.service.impl;

import com.cisdi.blog.dao.BlogRepository;
import com.cisdi.blog.entity.Blog;
import com.cisdi.blog.entity.Tag;
import com.cisdi.blog.entity.Type;
import com.cisdi.blog.exception.NotFoundException;
import com.cisdi.blog.service.BlogService;
import com.cisdi.blog.util.BeanUtilsExt;
import com.cisdi.blog.util.MarkdownUtils;
import com.cisdi.blog.vo.BlogQuery;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.*;
import java.util.*;

/**
 * @author pengyangyan
 * @version 1.0.0
 * @date 2020年03月19日 16:38:00
 */
@Service
public class BlogServiceImpl implements BlogService {

    @Autowired
    BlogRepository blogRepository;

    @Override
    public Long getBlogTotal() {
        return blogRepository.count();
    }

    @Override
    public Blog getBlog(Long id) {
        Blog one = blogRepository.getOne(id);
        if (one==null){
            throw new NotFoundException("博客不存在");
        }
        return one;
    }

    @Override
    public Blog show(Long id) {
        Blog one = blogRepository.getOne(id);
        if (one==null){
            throw new NotFoundException("博客不存在");
        }
        blogRepository.updateViews(one.getId(),one.getViews()+1);
        Blog blog = new Blog();
        BeanUtilsExt.copyBeanNotCopyNullValue(one,blog);
        String content = one.getContent();
        blog.setContent(MarkdownUtils.markdwonToHtmlExtensions(content));
        return blog;
    }

    @Override
    public Page listBlog(Pageable pageable, BlogQuery query) {
        return blogRepository.findAll((Specification<Blog>) (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (!StringUtils.isEmpty(query.getTitle())) {
                predicates.add(criteriaBuilder.like(root.<String>get( "title"), "%" + query.getTitle() + "%"));
            }
            if (query.getTypeId() != null) {
                predicates.add(criteriaBuilder.equal(root.<Type>get("type").get("id"), query.getTypeId()));
            }
            if (query.getRecommend()!=null && query.getRecommend()) {
                predicates.add(criteriaBuilder.equal(root.<Boolean>get("recommend"), query.getRecommend()));
            }
            criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));
            return null;
        }, pageable);
    }

    @Override
    public Page listBlog(Pageable pageable, String query) {
        query = "%"+query+"%";
        return blogRepository.findByQuery(query,pageable);
    }

    @Override
    public Page listBlog(Long tagId, Pageable pageable) {
        return blogRepository.findAll(new Specification<Blog>() {
            @Override
            public Predicate toPredicate(Root<Blog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Join join = root.join("tags");
                return criteriaBuilder.equal(join.get("id"),tagId);
            }
        },pageable);
}

    @Override
    public Blog saveBlog(Blog blog) {
        blog.setCreateTime(new Date());
        blog.setUpdateTime(new Date());
        blog.setViews(0);
        return blogRepository.save(blog);
    }

    @Override
    public Blog updateBlog(Long id,Blog blog) {
        Blog one = blogRepository.getOne(id);
        if (Objects.nonNull(one)){
            one.setUpdateTime(new Date());
            BeanUtilsExt.copyBeanNotCopyNullValue(blog,one);
//            BeanUtils.copyProperties(blog,one,"updateTime","createTime","views");
            return blogRepository.save(one);
        }else {
            throw new NotFoundException("更新的博客不存在");
        }

    }

    @Override
    public void removeBlog(Long id) {
        blogRepository.deleteById(id);
    }

    @Override
    public List<Blog> hotBlog(Integer size) {
        Sort sort = Sort.by(Sort.Direction.DESC,"updateTime","views");
        Pageable pageable = PageRequest.of(0,size,sort);
        return blogRepository.findTop(pageable);
    }

    @Override
    public List<Map<String, Object>> getArchiveMap() {
        List<String> years = blogRepository.getYears();
        List<Map<String, Object>>  result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(years)){
            Map<String,Object> list = new HashMap<>();
            for (String year : years) {
                List<Blog> blogs = blogRepository.getBlogByYears(year);
                list.put("year",year);
                list.put("list",blogs);
            }
            result.add(list);
        }
        return result;
    }
}
